package com.grace.util;

import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.grace.exception.ParamException;
import org.apache.commons.collections.MapUtils;

import javax.validation.*;
import java.util.*;

public class BeanValidator {
    //定义全局的校验工厂
    private static ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();

    /**
     * 校验单个对象或者参数
     *
     * @param t
     * @param groups
     * @param <T>
     * @return
     */
    //校验单个对象或者参数
    //public interface Map<K,V>
    public static <T> Map<String, String> validator(T t, Class... groups) { //??
        //创建一个验证工程
        Validator validator = validatorFactory.getValidator();
        //自动获取一个校验结果
        //public interface Set<E> extends Collection<E>
        //<T> Set<ConstraintViolation<T>> validate(T var1, Class<?>... var2);
        //可以自动地获取校验结果
        Set validatorResult = validator.validate(t, groups);
        //判断校验结果是否为空
        if (validatorResult.isEmpty()) {
            //如果错误信息为空，则返回一个集合（空的Map）
            return Collections.emptyMap();
        } else {
            //获取错误信息
            // public static <K, V> LinkedHashMap<K, V> newLinkedHashMap()
            //本质和new出来是一样的，是谷歌的写法
            LinkedHashMap errors = Maps.newLinkedHashMap();
            //迭代器
            Iterator iterator = validatorResult.iterator();
            //while
            while (iterator.hasNext()) {
                //获取set集合信息里面的单个值
                ConstraintViolation violation = (ConstraintViolation) iterator.next();
                //填充到错误信息中
                //key是错误字段，value是错误信息
                errors.put(violation.getPropertyPath().toString(), violation.getMessage());
            }
            return errors;
        }

    }

    /**
     * 验证List集合对象
     *
     * @param collection
     * @return
     */
    public static Map<String, String> validatorList(Collection<?> collection) {
        //使用继承校验，判断集合传过来的是否为空
        //传入一些语句做一些基础校验
        Preconditions.checkNotNull(collection);
        //迭代器
        Iterator iterator = collection.iterator();
        Map errors;
        //循环判断
        do {
            //取反，空值可以进
            if (!iterator.hasNext()) {
                //直接返回空map
                return Collections.emptyMap();
            }
            //如果不为空的话，取这个值
            Object object = iterator.next();
            errors = validator(object, new Class[0]);
        } while (errors.isEmpty());

        return errors;
    }

    /**
     * 对对象或者集合进行判断(传入object 自动匹配校验 最好有两个以上的对象或者集合进行判断）
     *
     * @param first
     * @param objects
     * @return
     */
    public static Map<String, String> validatorObject(Object first, Object... objects) {
        //如果传入的可变长参数不为空且长度大于0
        if (objects != null && objects.length > 0) {
            return validatorList(Lists.asList(first, objects));
        } else {   //否则进入单个长度的验证
            return validator(first, new Class[0]);
        }
    }

    /**
     * 在这里进行一个异常捕获
     *
     * @param param
     * @throws ParamException
     */
    public static void check(Object param) throws ParamException {
        //返回了校验结果
        Map<String, String> map = BeanValidator.validatorObject(param);
        //判断校验结果
        //if (map != null && map.entrySet().size() > 0) {
        if (MapUtils.isNotEmpty(map)) {
            throw new ParamException(map.toString());
        }

    }
}
